package com.pc.scrs.config;

import com.pc.scrs.filter.JwtFilter;
import com.pc.scrs.handler.*;
import com.pc.scrs.service.impl.LoginDetailService;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import javax.annotation.Resource;

@EnableWebSecurity //开启spring security
@EnableGlobalMethodSecurity(prePostEnabled = true)// 启用方法安全设置
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private LoginDetailService loginDetailService;

    @Resource
    private LoginSuccessHandler loginSuccessHandler;

    @Resource
    private LoginFailureHandler loginFailureHandler;

    @Resource
    private SimpLogoutSuccessHandler simpLogoutSuccessHandler;

    @Resource
    private SimpleAuthenticationEntryPoint simpleAuthenticationEntryPoint;

    @Resource
    private SimpleAccessDeniedHandler simpleAccessDeniedHandler;

    @Resource
    private JwtFilter jwtFilter;

    /**
     *  注入passwordEncoder密码管理器
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    /**
     * 解决跨域同源问题
     * @return
     */
    private CorsConfigurationSource corsConfigurationSource(){
        CorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");// * 表示对所有的地址都可以访问
        corsConfiguration.addAllowedHeader("*");// 跨域的请求头
        corsConfiguration.addAllowedMethod("*");// 跨域的请求方法
        ((UrlBasedCorsConfigurationSource)source).registerCorsConfiguration("/**", corsConfiguration);
        return source;
    }

    /**
     * 处理security的登录认证
     * 通过LoginDetailService来对比
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(loginDetailService).passwordEncoder(passwordEncoder());
    }

    /**
     * 重写security的过滤器链
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated();
        http.formLogin()
                .successHandler(loginSuccessHandler)//登录成功处理器
                .failureHandler(loginFailureHandler)//登录失败处理器
                .permitAll();//放行login的访问权

        http.logout().logoutSuccessHandler(simpLogoutSuccessHandler);//退出成功处理器

        http.exceptionHandling()
                .authenticationEntryPoint(simpleAuthenticationEntryPoint)//认证异常处理器
                .accessDeniedHandler(simpleAccessDeniedHandler);//鉴权异常处理器
        http.csrf().disable();//关闭跨站请求伪造防护
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);//前后端分离禁用session
        //添加自定义的jwtFilter过滤器
        http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
    }
}
